package cool.mtc.io.util;

import cool.mtc.core.util.FileUtil;
import cool.mtc.core.util.StringUtil;
import lombok.Cleanup;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.util.ResourceUtils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.UUID;

/**
 * @author 明河
 */
public abstract class ResourceUtil extends ResourceUtils {

    /**
     * 资源读取器
     */
    private static final DefaultResourceLoader RESOURCE_LOADER = new DefaultResourceLoader();

    /**
     * 根据资源位置获取资源
     *
     * @param resourceLocation 资源位置
     * @return Resource
     */
    public static Resource getResource(String resourceLocation) {
        Resource resource;
        if (resourceLocation.startsWith(CLASSPATH_URL_PREFIX)) {
            resource = getResourceByClasspath(resourceLocation);
        } else {
            resource = getResourceByFilesystem(resourceLocation);
        }
        return resource;
    }

    /**
     * 根据资源位置获取资源（使用classpath模式）
     *
     * @param resourceLocation 资源位置
     * @return Resource
     */
    public static Resource getResourceByClasspath(String resourceLocation) {
        return RESOURCE_LOADER.getResource(resourceLocation);
    }

    /**
     * 根据资源位置获取资源（使用filesystem模式）
     *
     * @param resourceLocation 资源位置
     * @return Resource
     */
    public static Resource getResourceByFilesystem(String resourceLocation) {
        if (resourceLocation.startsWith(FILE_URL_PREFIX)) {
            return new FileSystemResource(resourceLocation.substring(FILE_URL_PREFIX.length()));
        }
        return new FileSystemResource(resourceLocation);
    }

    /**
     * 根据资源位置创建资源
     *
     * @param resourceLocation 资源位置
     * @return Resource
     */
    public static Resource createResource(String resourceLocation) throws IOException {
        return createResource(resourceLocation, false);
    }

    /**
     * 根据资源位置创建资源
     *
     * @param resourceLocation 资源位置
     * @param alwaysCreate     是否始终创建
     */
    public static Resource createResource(String resourceLocation, boolean alwaysCreate) throws IOException {
        Resource resource;
        if (resourceLocation.startsWith(CLASSPATH_URL_PREFIX)) {
            resource = createResourceByClasspath(resourceLocation, alwaysCreate);
        } else if (resourceLocation.startsWith(FILE_URL_PREFIX)) {
            resource = createResourceByFilesystem(resourceLocation, alwaysCreate);
        } else {
            resource = createResourceByFilesystem(resourceLocation, alwaysCreate);
        }
        return resource;
    }

    /**
     * 根据资源位置创建资源（使用classpath模式）
     *
     * @param resourceLocation 资源位置
     * @return Resource
     */
    public static Resource createResourceByClasspath(String resourceLocation, boolean alwaysCreate) throws IOException {
        String path = ResourceUtils.getURL(ResourceUtils.CLASSPATH_URL_PREFIX).getPath();
        path = URLDecoder.decode(path, StandardCharsets.UTF_8.displayName());
        File file = new File(path, resourceLocation.substring(CLASSPATH_URL_PREFIX.length()));
        return getResourceByFile(file, alwaysCreate);
    }

    /**
     * 根据资源位置创建资源（使用filesystem模式）
     *
     * @param resourceLocation 资源位置
     * @return Resource
     */
    public static Resource createResourceByFilesystem(String resourceLocation, boolean alwaysCreate) throws IOException {
        File file;
        if (resourceLocation.startsWith(FILE_URL_PREFIX)) {
            file = new File(resourceLocation.substring(FILE_URL_PREFIX.length()));
        } else {
            file = new File(resourceLocation);
        }
        return getResourceByFile(file, alwaysCreate);
    }

    /**
     * 根据文件获取资源，文件不存在则新建
     *
     * @param file 文件对象
     * @return Resource
     */
    private static FileSystemResource getResourceByFile(File file, boolean alwaysCreate) throws IOException {
        if (alwaysCreate) {
            FileUtil.generateFile(file.getAbsolutePath());
        }
        if (!file.exists()) {
            FileUtil.generateFile(file.getAbsolutePath());
        }
        return new FileSystemResource(file);
    }

    /**
     * 增加UUID文件夹
     */
    public static String plusUUIDFolder(String fileName) {
        return UUID.randomUUID().toString() + StringUtil.SLASH + fileName;
    }

    /**
     * 获取文件输入流的md5值
     */
    public static String md5(Resource resource) throws IOException {
        @Cleanup InputStream inputStream = resource.getInputStream();
        return DigestUtils.md5Hex(inputStream);
    }

    public static String sha256(Resource resource) throws IOException {
        @Cleanup InputStream inputStream = resource.getInputStream();
        return DigestUtils.sha256Hex(inputStream);
    }
}
